#pragma once

#include"sem.hpp"
#include<iostream>
#include<pthread.h>
#include<vector>
using namespace std;

static int defaultcap=5;
template<class T>
class RingQueue
{
public:
    RingQueue(int mp=defaultcap)
    :max_cap(mp),rq(mp),p_index(0),c_index(0),
    p_sem(mp),c_sem(0)
    {
        pthread_mutex_init(&p_mutex,nullptr);
        pthread_mutex_init(&c_mutex,nullptr);
    }
    void Push(T& in)
    {
        p_sem.P();

        pthread_mutex_lock(&p_mutex);
        rq[p_index++]=in;
        p_index%=max_cap;
        pthread_mutex_unlock(&p_mutex);

        c_sem.V();
    }
    T Pop()
    {
        c_sem.P();

        pthread_mutex_lock(&c_mutex);
        T out=rq[c_index++];
        c_index%=max_cap;
        pthread_mutex_unlock(&c_mutex);

        p_sem.V();
        return out;
    }
    ~RingQueue()
    {
        pthread_mutex_destroy(&p_mutex);
        pthread_mutex_destroy(&c_mutex);
    }
private:
    vector<T> rq;       //用vector模拟环形队列
    int max_cap;        //队列的容量
    int p_index;        //生产者下标
    int c_index;        //消费者下标
    Sem p_sem;          //空间信号量（生产者所关注的信号量）
    Sem c_sem;          //数据信号量（消费者所关注的信号量）
    pthread_mutex_t p_mutex;
    pthread_mutex_t c_mutex;
};